package com.strato.datafactory.v1_0_0.factory.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;

import com.strato.base.cache.v1_0_0.TimedReference;
import com.strato.datafactory.v1_0_0.api.DataFilter;


public class DefaultDataCacheManager implements DataCacheManager{
	
	private Map<String,Map<Integer,TimedReference<Map<String,Object>>>> dataCache;	
	
	@Override
	public void set(String dataId,List<DataFilter> filters,Map<String,Object> data, String cacheTTL){
		if(dataCache==null){
			dataCache=new HashMap<String,Map<Integer,TimedReference<Map<String,Object>>>>();
		}
		Map<Integer,TimedReference<Map<String,Object>>> dataIdCache=dataCache.get(dataId);
		if(dataIdCache==null){
			dataIdCache=new HashMap<Integer,TimedReference<Map<String,Object>>>();
			dataCache.put(dataId, dataIdCache);
		}
		int hash=filters==null?ObjectUtils.NULL.hashCode():hash(filters);
		TimedReference<Map<String,Object>> ref=new TimedReference<Map<String,Object>>(data,Integer.parseInt(cacheTTL));
		dataIdCache.put(Integer.valueOf(hash), ref);
	}
	
	private int hash(List<DataFilter> filters) {
		HashCodeBuilder hb=new HashCodeBuilder();
		for(Iterator<DataFilter> iter=filters.iterator();iter.hasNext();){
			DataFilter o=iter.next();
			hb.append(o);
		}
		return hb.toHashCode();
	}

	public Map<String,Object> get(String dataId,List<DataFilter> filters){
		if(dataCache == null){
			return null;
		}
		Map<Integer, TimedReference<Map<String, Object>>> dataIdCache = dataCache.get(dataId);
		if(dataIdCache==null){
			return null;
		}
		int hash=filters==null?ObjectUtils.NULL.hashCode():hash(filters);
		TimedReference<Map<String, Object>> ref=dataIdCache.get(Integer.valueOf(hash));
		if(ref==null||ref.isExpired()){
			return null;
		}
		return ref.getObject();
	}
	
	
	public void remove(String dataId){
		if(dataCache!=null){
			dataCache.remove(dataId);
		}
	}
	
	public void clear(){
		dataCache.clear();
	}
	
	
}
